home *** CD-ROM | disk | FTP | other *** search
/ AmigActive 10 / AACD 10.iso / AACD / Games / MAME / src / cpu / z8000 / z8000.c < prev    next >
C/C++ Source or Header  |  2000-04-23  |  23KB  |  771 lines

  1. /*****************************************************************************
  2.  *
  3.  *     z8000.c
  4.  *     Portable Z8000(2) emulator
  5.  *     Z8000 MAME interface
  6.  *
  7.  *     Copyright (C) 1998,1999 Juergen Buchmueller, all rights reserved.
  8.  *     Bug fixes and MSB_FIRST compliance Ernesto Corvi.
  9.  *
  10.  *     - This source code is released as freeware for non-commercial purposes.
  11.  *     - You are free to use and redistribute this code in modified or
  12.  *       unmodified form, provided you list me in the credits.
  13.  *     - If you modify this source code, you must add a notice to each modified
  14.  *       source file that it has been changed.  If you're a nice person, you
  15.  *       will clearly mark each change too.  :)
  16.  *     - If you wish to use this for commercial purposes, please contact me at
  17.  *       pullmoll@t-online.de
  18.  *     - The author of this copywritten work reserves the right to change the
  19.  *     terms of its usage and license at any time, including retroactively
  20.  *   - This entire notice must remain in the source code.
  21.  *
  22.  *****************************************************************************/
  23.  
  24. #include "driver.h"
  25. #include "mamedbg.h"
  26. #include "z8000.h"
  27. #include "z8000cpu.h"
  28.  
  29. #define VERBOSE 0
  30.  
  31.  
  32. #if VERBOSE
  33. #define LOG(x)    logerror x
  34. #else
  35. #define LOG(x)
  36. #endif
  37.  
  38. static UINT8 z8000_reg_layout[] = {
  39.     Z8000_PC, Z8000_NSP, Z8000_FCW, Z8000_PSAP, Z8000_REFRESH, -1,
  40.     Z8000_R0, Z8000_R1, Z8000_R2, Z8000_R3, Z8000_R4, Z8000_R5, Z8000_R6, Z8000_R7, -1,
  41.     Z8000_R8, Z8000_R9, Z8000_R10,Z8000_R11,Z8000_R12,Z8000_R13,Z8000_R14,Z8000_R15,-1,
  42.     Z8000_IRQ_REQ, Z8000_IRQ_SRV, Z8000_IRQ_VEC, Z8000_NMI_STATE, Z8000_NVI_STATE, Z8000_VI_STATE, 0
  43. };
  44.  
  45. static UINT8 z8000_win_layout[] = {
  46.      0, 0,80, 4,    /* register window (top rows) */
  47.      0, 5,26,17,    /* disassembler window (left colums) */
  48.     27, 5,53, 8,    /* memory #1 window (right, upper middle) */
  49.     27,14,53, 8,    /* memory #2 window (right, lower middle) */
  50.      0,23,80, 1,    /* command line window (bottom rows) */
  51. };
  52.  
  53. /* opcode execution table */
  54. Z8000_exec *z8000_exec = NULL;
  55.  
  56. typedef union {
  57.     UINT8   B[16]; /* RL0,RH0,RL1,RH1...RL7,RH7 */
  58.     UINT16  W[16]; /* R0,R1,R2...R15 */
  59.     UINT32  L[8];  /* RR0,RR2,RR4..RR14 */
  60.     UINT64  Q[4];  /* RQ0,RQ4,..RQ12 */
  61. }   z8000_reg_file;
  62.  
  63. typedef struct {
  64.     UINT16  op[4];      /* opcodes/data of current instruction */
  65.     UINT16    ppc;        /* previous program counter */
  66.     UINT16  pc;         /* program counter */
  67.     UINT16  psap;       /* program status pointer */
  68.     UINT16  fcw;        /* flags and control word */
  69.     UINT16  refresh;    /* refresh timer/counter */
  70.     UINT16  nsp;        /* system stack pointer */
  71.     UINT16  irq_req;    /* CPU is halted, interrupt or trap request */
  72.     UINT16  irq_srv;    /* serviced interrupt request */
  73.     UINT16  irq_vec;    /* interrupt vector */
  74.     z8000_reg_file regs;/* registers */
  75.     int nmi_state;        /* NMI line state */
  76.     int irq_state[2];    /* IRQ line states (NVI, VI) */
  77.     int (*irq_callback)(int irqline);
  78. }   z8000_Regs;
  79.  
  80. int z8000_ICount;
  81.  
  82. /* current CPU context */
  83. static z8000_Regs Z;
  84.  
  85. /* zero, sign and parity flags for logical byte operations */
  86. static UINT8 z8000_zsp[256];
  87.  
  88. /* conversion table for Z8000 DAB opcode */
  89. #include "z8000dab.h"
  90.  
  91. /**************************************************************************
  92.  * This is the register file layout:
  93.  *
  94.  * BYTE        WORD         LONG           QUAD
  95.  * msb     lsb       bits           bits             bits
  96.  * RH0 - RL0   R 0 15- 0    RR 0  31-16    RQ 0  63-48
  97.  * RH1 - RL1   R 1 15- 0          15- 0          47-32
  98.  * RH2 - RL2   R 2 15- 0    RR 2  31-16          31-16
  99.  * RH3 - RL3   R 3 15- 0          15- 0          15- 0
  100.  * RH4 - RL4   R 4 15- 0    RR 4  31-16    RQ 4  63-48
  101.  * RH5 - RL5   R 5 15- 0          15- 0          47-32
  102.  * RH6 - RL6   R 6 15- 0    RR 6  31-16          31-16
  103.  * RH7 - RL7   R 7 15- 0          15- 0          15- 0
  104.  *               R 8 15- 0    RR 8  31-16    RQ 8  63-48
  105.  *               R 9 15- 0          15- 0          47-32
  106.  *               R10 15- 0    RR10  31-16          31-16
  107.  *               R11 15- 0          15- 0          15- 0
  108.  *               R12 15- 0    RR12  31-16    RQ12  63-48
  109.  *               R13 15- 0          15- 0          47-32
  110.  *               R14 15- 0    RR14  31-16          31-16
  111.  *               R15 15- 0          15- 0          15- 0
  112.  *
  113.  * Note that for LSB_FIRST machines we have the case that the RR registers
  114.  * use the lower numbered R registers in the higher bit positions.
  115.  * And also the RQ registers use the lower numbered RR registers in the
  116.  * higher bit positions.
  117.  * That's the reason for the ordering in the following pointer table.
  118.  **************************************************************************/
  119. #ifdef    LSB_FIRST
  120.     /* pointers to byte (8bit) registers */
  121.     static UINT8    *pRB[16] =
  122.     {
  123.         &Z.regs.B[ 7],&Z.regs.B[ 5],&Z.regs.B[ 3],&Z.regs.B[ 1],
  124.         &Z.regs.B[15],&Z.regs.B[13],&Z.regs.B[11],&Z.regs.B[ 9],
  125.         &Z.regs.B[ 6],&Z.regs.B[ 4],&Z.regs.B[ 2],&Z.regs.B[ 0],
  126.         &Z.regs.B[14],&Z.regs.B[12],&Z.regs.B[10],&Z.regs.B[ 8]
  127.     };
  128.  
  129.     static UINT16    *pRW[16] =
  130.     {
  131.         &Z.regs.W[ 3],&Z.regs.W[ 2],&Z.regs.W[ 1],&Z.regs.W[ 0],
  132.         &Z.regs.W[ 7],&Z.regs.W[ 6],&Z.regs.W[ 5],&Z.regs.W[ 4],
  133.         &Z.regs.W[11],&Z.regs.W[10],&Z.regs.W[ 9],&Z.regs.W[ 8],
  134.         &Z.regs.W[15],&Z.regs.W[14],&Z.regs.W[13],&Z.regs.W[12]
  135.     };
  136.  
  137.     /* pointers to long (32bit) registers */
  138.     static UINT32    *pRL[16] =
  139.     {
  140.         &Z.regs.L[ 1],&Z.regs.L[ 1],&Z.regs.L[ 0],&Z.regs.L[ 0],
  141.         &Z.regs.L[ 3],&Z.regs.L[ 3],&Z.regs.L[ 2],&Z.regs.L[ 2],
  142.         &Z.regs.L[ 5],&Z.regs.L[ 5],&Z.regs.L[ 4],&Z.regs.L[ 4],
  143.         &Z.regs.L[ 7],&Z.regs.L[ 7],&Z.regs.L[ 6],&Z.regs.L[ 6]
  144.     };
  145.  
  146. #else    /* MSB_FIRST */
  147.  
  148.     /* pointers to byte (8bit) registers */
  149.     static UINT8    *pRB[16] =
  150.     {
  151.         &Z.regs.B[ 0],&Z.regs.B[ 2],&Z.regs.B[ 4],&Z.regs.B[ 6],
  152.         &Z.regs.B[ 8],&Z.regs.B[10],&Z.regs.B[12],&Z.regs.B[14],
  153.         &Z.regs.B[ 1],&Z.regs.B[ 3],&Z.regs.B[ 5],&Z.regs.B[ 7],
  154.         &Z.regs.B[ 9],&Z.regs.B[11],&Z.regs.B[13],&Z.regs.B[15]
  155.     };
  156.  
  157.     /* pointers to word (16bit) registers */
  158.     static UINT16    *pRW[16] =
  159.     {
  160.         &Z.regs.W[ 0],&Z.regs.W[ 1],&Z.regs.W[ 2],&Z.regs.W[ 3],
  161.         &Z.regs.W[ 4],&Z.regs.W[ 5],&Z.regs.W[ 6],&Z.regs.W[ 7],
  162.         &Z.regs.W[ 8],&Z.regs.W[ 9],&Z.regs.W[10],&Z.regs.W[11],
  163.         &Z.regs.W[12],&Z.regs.W[13],&Z.regs.W[14],&Z.regs.W[15]
  164.     };
  165.  
  166.     /* pointers to long (32bit) registers */
  167.     static UINT32    *pRL[16] =
  168.     {
  169.         &Z.regs.L[ 0],&Z.regs.L[ 0],&Z.regs.L[ 1],&Z.regs.L[ 1],
  170.         &Z.regs.L[ 2],&Z.regs.L[ 2],&Z.regs.L[ 3],&Z.regs.L[ 3],
  171.         &Z.regs.L[ 4],&Z.regs.L[ 4],&Z.regs.L[ 5],&Z.regs.L[ 5],
  172.         &Z.regs.L[ 6],&Z.regs.L[ 6],&Z.regs.L[ 7],&Z.regs.L[ 7]
  173.     };
  174.  
  175. #endif
  176.  
  177. /* pointers to quad word (64bit) registers */
  178. static UINT64   *pRQ[16] = {
  179.     &Z.regs.Q[ 0],&Z.regs.Q[ 0],&Z.regs.Q[ 0],&Z.regs.Q[ 0],
  180.     &Z.regs.Q[ 1],&Z.regs.Q[ 1],&Z.regs.Q[ 1],&Z.regs.Q[ 1],
  181.     &Z.regs.Q[ 2],&Z.regs.Q[ 2],&Z.regs.Q[ 2],&Z.regs.Q[ 2],
  182.     &Z.regs.Q[ 3],&Z.regs.Q[ 3],&Z.regs.Q[ 3],&Z.regs.Q[ 3]};
  183.  
  184. INLINE UINT16 RDOP(void)
  185. {
  186.     UINT16 res = cpu_readop16(PC);
  187.     PC += 2;
  188.     return res;
  189. }
  190.  
  191. INLINE UINT8 RDMEM_B(UINT16 addr)
  192. {
  193.     return cpu_readmem16bew(addr);
  194. }
  195.  
  196. INLINE UINT16 RDMEM_W(UINT16 addr)
  197. {
  198.     addr &= ~1;
  199.     return cpu_readmem16bew_word(addr);
  200. }
  201.  
  202. INLINE UINT32 RDMEM_L(UINT16 addr)
  203. {
  204.     UINT32 result;
  205.     addr &= ~1;
  206.     result = cpu_readmem16bew_word(addr) << 16;
  207.     return result + cpu_readmem16bew_word(addr + 2);
  208. }
  209.  
  210. INLINE void WRMEM_B(UINT16 addr, UINT8 value)
  211. {
  212.     cpu_writemem16bew(addr, value);
  213. }
  214.  
  215. INLINE void WRMEM_W(UINT16 addr, UINT16 value)
  216. {
  217.     addr &= ~1;
  218.     cpu_writemem16bew_word(addr, value);
  219. }
  220.  
  221. INLINE void WRMEM_L(UINT16 addr, UINT32 value)
  222. {
  223.     addr &= ~1;
  224.     cpu_writemem16bew_word(addr, value >> 16);
  225.     cpu_writemem16bew_word((UINT16)(addr + 2), value & 0xffff);
  226. }
  227.  
  228. INLINE UINT8 RDPORT_B(int mode, UINT16 addr)
  229. {
  230.     if( mode == 0 )
  231.     {
  232.         return cpu_readport(addr);
  233.     }
  234.     else
  235.     {
  236.         /* how to handle MMU reads? */
  237.         return 0x00;
  238.     }
  239. }
  240.  
  241. INLINE UINT16 RDPORT_W(int mode, UINT16 addr)
  242. {
  243.     if( mode == 0 )
  244.     {
  245.         return cpu_readport((UINT16)(addr)) +
  246.               (cpu_readport((UINT16)(addr+1)) << 8);
  247.     }
  248.     else
  249.     {
  250.         /* how to handle MMU reads? */
  251.         return 0x0000;
  252.     }
  253. }
  254.  
  255. INLINE UINT32 RDPORT_L(int mode, UINT16 addr)
  256. {
  257.     if( mode == 0 )
  258.     {
  259.         return    cpu_readport((UINT16)(addr)) +
  260.                (cpu_readport((UINT16)(addr+1)) <<  8) +
  261.                (cpu_readport((UINT16)(addr+2)) << 16) +
  262.                (cpu_readport((UINT16)(addr+3)) << 24);
  263.     }
  264.     else
  265.     {
  266.         /* how to handle MMU reads? */
  267.         return 0x00000000;
  268.     }
  269. }
  270.  
  271. INLINE void WRPORT_B(int mode, UINT16 addr, UINT8 value)
  272. {
  273.     if( mode == 0 )
  274.     {
  275.         cpu_writeport(addr,value);
  276.     }
  277.     else
  278.     {
  279.         /* how to handle MMU writes? */
  280.     }
  281. }
  282.  
  283. INLINE void WRPORT_W(int mode, UINT16 addr, UINT16 value)
  284. {
  285.     if( mode == 0 )
  286.     {
  287.         cpu_writeport((UINT16)(addr),value & 0xff);
  288.         cpu_writeport((UINT16)(addr+1),(value >> 8) & 0xff);
  289.     }
  290.     else
  291.     {
  292.         /* how to handle MMU writes? */
  293.     }
  294. }
  295.  
  296. INLINE void WRPORT_L(int mode, UINT16 addr, UINT32 value)
  297. {
  298.     if( mode == 0 )
  299.     {
  300.         cpu_writeport((UINT16)(addr),value & 0xff);
  301.         cpu_writeport((UINT16)(addr+1),(value >> 8) & 0xff);
  302.         cpu_writeport((UINT16)(addr+2),(value >> 16) & 0xff);
  303.         cpu_writeport((UINT16)(addr+3),(value >> 24) & 0xff);
  304.     }
  305.     else
  306.     {
  307.         /* how to handle MMU writes? */
  308.     }
  309. }
  310.  
  311. #include "z8000ops.c"
  312. #include "z8000tbl.c"
  313.  
  314. INLINE void set_irq(int type)
  315. {
  316.     switch ((type >> 8) & 255)
  317.     {
  318.         case Z8000_INT_NONE >> 8:
  319.             return;
  320.         case Z8000_TRAP >> 8:
  321.             if (IRQ_SRV >= Z8000_TRAP)
  322.                 return; /* double TRAP.. very bad :( */
  323.             IRQ_REQ = type;
  324.             break;
  325.         case Z8000_NMI >> 8:
  326.             if (IRQ_SRV >= Z8000_NMI)
  327.                 return; /* no NMIs inside trap */
  328.             IRQ_REQ = type;
  329.             break;
  330.         case Z8000_SEGTRAP >> 8:
  331.             if (IRQ_SRV >= Z8000_SEGTRAP)
  332.                 return; /* no SEGTRAPs inside NMI/TRAP */
  333.             IRQ_REQ = type;
  334.             break;
  335.         case Z8000_NVI >> 8:
  336.             if (IRQ_SRV >= Z8000_NVI)
  337.                 return; /* no NVIs inside SEGTRAP/NMI/TRAP */
  338.             IRQ_REQ = type;
  339.             break;
  340.         case Z8000_VI >> 8:
  341.             if (IRQ_SRV >= Z8000_VI)
  342.                 return; /* no VIs inside NVI/SEGTRAP/NMI/TRAP */
  343.             IRQ_REQ = type;
  344.             break;
  345.         case Z8000_SYSCALL >> 8:
  346.             LOG(("Z8K#%d SYSCALL $%02x\n", cpu_getactivecpu(), type & 0xff));
  347.             IRQ_REQ = type;
  348.             break;
  349.         default:
  350.             logerror("Z8000 invalid Cause_Interrupt %04x\n", type);
  351.             return;
  352.     }
  353.     /* set interrupt request flag, reset HALT flag */
  354.     IRQ_REQ = type & ~Z8000_HALT;
  355. }
  356.  
  357.  
  358. INLINE void Interrupt(void)
  359. {
  360.     UINT16 fcw = FCW;
  361.  
  362.     if (IRQ_REQ & Z8000_NVI)
  363.     {
  364.         int type = (*Z.irq_callback)(0);
  365.         set_irq(type);
  366.     }
  367.  
  368.     if (IRQ_REQ & Z8000_VI)
  369.     {
  370.         int type = (*Z.irq_callback)(1);
  371.         set_irq(type);
  372.     }
  373.  
  374.    /* trap ? */
  375.    if ( IRQ_REQ & Z8000_TRAP )
  376.    {
  377.         CHANGE_FCW(fcw | F_S_N);/* swap to system stack */
  378.         PUSHW( SP, PC );        /* save current PC */
  379.         PUSHW( SP, fcw );       /* save current FCW */
  380.         PUSHW( SP, IRQ_REQ );   /* save interrupt/trap type tag */
  381.         IRQ_SRV = IRQ_REQ;
  382.         IRQ_REQ &= ~Z8000_TRAP;
  383.         PC = TRAP;
  384.         LOG(("Z8K#%d trap $%04x\n", cpu_getactivecpu(), PC ));
  385.    }
  386.    else
  387.    if ( IRQ_REQ & Z8000_SYSCALL )
  388.    {
  389.         CHANGE_FCW(fcw | F_S_N);/* swap to system stack */
  390.         PUSHW( SP, PC );        /* save current PC */
  391.         PUSHW( SP, fcw );       /* save current FCW */
  392.         PUSHW( SP, IRQ_REQ );   /* save interrupt/trap type tag */
  393.         IRQ_SRV = IRQ_REQ;
  394.         IRQ_REQ &= ~Z8000_SYSCALL;
  395.         PC = SYSCALL;
  396.         LOG(("Z8K#%d syscall $%04x\n", cpu_getactivecpu(), PC ));
  397.    }
  398.    else
  399.    if ( IRQ_REQ & Z8000_SEGTRAP )
  400.    {
  401.         CHANGE_FCW(fcw | F_S_N);/* swap to system stack */
  402.         PUSHW( SP, PC );        /* save current PC */
  403.         PUSHW( SP, fcw );       /* save current FCW */
  404.         PUSHW( SP, IRQ_REQ );   /* save interrupt/trap type tag */
  405.         IRQ_SRV = IRQ_REQ;
  406.         IRQ_REQ &= ~Z8000_SEGTRAP;
  407.         PC = SEGTRAP;
  408.         LOG(("Z8K#%d segtrap $%04x\n", cpu_getactivecpu(), PC ));
  409.    }
  410.    else
  411.    if ( IRQ_REQ & Z8000_NMI )
  412.    {
  413.         CHANGE_FCW(fcw | F_S_N);/* swap to system stack */
  414.         PUSHW( SP, PC );        /* save current PC */
  415.         PUSHW( SP, fcw );       /* save current FCW */
  416.         PUSHW( SP, IRQ_REQ );   /* save interrupt/trap type tag */
  417.         IRQ_SRV = IRQ_REQ;
  418.         fcw = RDMEM_W( NMI );
  419.         PC = RDMEM_W( NMI + 2 );
  420.         IRQ_REQ &= ~Z8000_NMI;
  421.         CHANGE_FCW(fcw);
  422.         PC = NMI;
  423.         LOG(("Z8K#%d NMI $%04x\n", cpu_getactivecpu(), PC ));
  424.     }
  425.     else
  426.     if ( (IRQ_REQ & Z8000_NVI) && (FCW & F_NVIE) )
  427.     {
  428.         CHANGE_FCW(fcw | F_S_N);/* swap to system stack */
  429.         PUSHW( SP, PC );        /* save current PC */
  430.         PUSHW( SP, fcw );       /* save current FCW */
  431.         PUSHW( SP, IRQ_REQ );   /* save interrupt/trap type tag */
  432.         IRQ_SRV = IRQ_REQ;
  433.         fcw = RDMEM_W( NVI );
  434.         PC = RDMEM_W( NVI + 2 );
  435.         IRQ_REQ &= ~Z8000_NVI;
  436.         CHANGE_FCW(fcw);
  437.         LOG(("Z8K#%d NVI $%04x\n", cpu_getactivecpu(), PC ));
  438.     }
  439.     else
  440.     if ( (IRQ_REQ & Z8000_VI) && (FCW & F_VIE) )
  441.     {
  442.         CHANGE_FCW(fcw | F_S_N);/* swap to system stack */
  443.         PUSHW( SP, PC );        /* save current PC */
  444.         PUSHW( SP, fcw );       /* save current FCW */
  445.         PUSHW( SP, IRQ_REQ );   /* save interrupt/trap type tag */
  446.         IRQ_SRV = IRQ_REQ;
  447.         fcw = RDMEM_W( IRQ_VEC );
  448.         PC = RDMEM_W( VEC00 + 2 * (IRQ_REQ & 0xff) );
  449.         IRQ_REQ &= ~Z8000_VI;
  450.         CHANGE_FCW(fcw);
  451.         LOG(("Z8K#%d VI [$%04x/$%04x] fcw $%04x, pc $%04x\n", cpu_getactivecpu(), IRQ_VEC, VEC00 + VEC00 + 2 * (IRQ_REQ & 0xff), FCW, PC ));
  452.     }
  453. }
  454.  
  455.  
  456. void z8000_reset(void *param)
  457. {
  458.     z8000_init();
  459.     memset(&Z, 0, sizeof(z8000_Regs));
  460.     FCW = RDMEM_W( 2 ); /* get reset FCW */
  461.     PC    = RDMEM_W( 4 ); /* get reset PC  */
  462.     change_pc16bew(PC);
  463. }
  464.  
  465. void z8000_exit(void)
  466. {
  467.     z8000_deinit();
  468. }
  469.  
  470. int z8000_execute(int cycles)
  471. {
  472.     z8000_ICount = cycles;
  473.  
  474.     do
  475.     {
  476.         /* any interrupt request pending? */
  477.         if (IRQ_REQ)
  478.             Interrupt();
  479.  
  480.         CALL_MAME_DEBUG;
  481.  
  482.         if (IRQ_REQ & Z8000_HALT)
  483.         {
  484.             z8000_ICount = 0;
  485.         }
  486.         else
  487.         {
  488.             Z8000_exec *exec;
  489.             Z.op[0] = RDOP();
  490.             exec = &z8000_exec[Z.op[0]];
  491.  
  492.             if (exec->size > 1)
  493.                 Z.op[1] = RDOP();
  494.             if (exec->size > 2)
  495.                 Z.op[2] = RDOP();
  496.  
  497.             z8000_ICount -= exec->cycles;
  498.             (*exec->opcode)();
  499.  
  500.         }
  501.     } while (z8000_ICount > 0);
  502.  
  503.     return cycles - z8000_ICount;
  504.  
  505. }
  506.  
  507. unsigned z8000_get_context(void *dst)
  508. {
  509.     if( dst )
  510.         *(z8000_Regs*)dst = Z;
  511.     return sizeof(z8000_Regs);
  512. }
  513.  
  514. void z8000_set_context(void *src)
  515. {
  516.     if( src )
  517.     {
  518.         Z = *(z8000_Regs*)src;
  519.         change_pc16bew(PC);
  520.     }
  521. }
  522.  
  523. unsigned z8000_get_pc(void)
  524. {
  525.     return PC;
  526. }
  527.  
  528. void z8000_set_pc(unsigned val)
  529. {
  530.     PC = val;
  531.     change_pc16bew(PC);
  532. }
  533.  
  534. unsigned z8000_get_sp(void)
  535. {
  536.     return NSP;
  537. }
  538.  
  539. void z8000_set_sp(unsigned val)
  540. {
  541.     NSP = val;
  542. }
  543.  
  544. unsigned z8000_get_reg(int regnum)
  545. {
  546.     switch( regnum )
  547.     {
  548.         case Z8000_PC: return PC;
  549.         case Z8000_NSP: return NSP;
  550.         case Z8000_FCW: return FCW;
  551.         case Z8000_PSAP: return PSAP;
  552.         case Z8000_REFRESH: return REFRESH;
  553.         case Z8000_IRQ_REQ: return IRQ_REQ;
  554.         case Z8000_IRQ_SRV: return IRQ_SRV;
  555.         case Z8000_IRQ_VEC: return IRQ_VEC;
  556.         case Z8000_R0: return RW( 0);
  557.         case Z8000_R1: return RW( 1);
  558.         case Z8000_R2: return RW( 2);
  559.         case Z8000_R3: return RW( 3);
  560.         case Z8000_R4: return RW( 4);
  561.         case Z8000_R5: return RW( 5);
  562.         case Z8000_R6: return RW( 6);
  563.         case Z8000_R7: return RW( 7);
  564.         case Z8000_R8: return RW( 8);
  565.         case Z8000_R9: return RW( 9);
  566.         case Z8000_R10: return RW(10);
  567.         case Z8000_R11: return RW(11);
  568.         case Z8000_R12: return RW(12);
  569.         case Z8000_R13: return RW(13);
  570.         case Z8000_R14: return RW(14);
  571.         case Z8000_R15: return RW(15);
  572.         case Z8000_NMI_STATE: return Z.nmi_state;
  573.         case Z8000_NVI_STATE: return Z.irq_state[0];
  574.         case Z8000_VI_STATE: return Z.irq_state[1];
  575.         case REG_PREVIOUSPC: return PPC;
  576.         default:
  577.             if( regnum <= REG_SP_CONTENTS )
  578.             {
  579.                 unsigned offset = NSP + 2 * (REG_SP_CONTENTS - regnum);
  580.                 if( offset < 0xffff )
  581.                     return RDMEM_W( offset );
  582.             }
  583.     }
  584.     return 0;
  585. }
  586.  
  587. void z8000_set_reg(int regnum, unsigned val)
  588. {
  589.     switch( regnum )
  590.     {
  591.         case Z8000_PC: PC = val; break;
  592.         case Z8000_NSP: NSP = val; break;
  593.         case Z8000_FCW: FCW = val; break;
  594.         case Z8000_PSAP: PSAP = val; break;
  595.         case Z8000_REFRESH: REFRESH = val; break;
  596.         case Z8000_IRQ_REQ: IRQ_REQ = val; break;
  597.         case Z8000_IRQ_SRV: IRQ_SRV = val; break;
  598.         case Z8000_IRQ_VEC: IRQ_VEC = val; break;
  599.         case Z8000_R0: RW( 0) = val; break;
  600.         case Z8000_R1: RW( 1) = val; break;
  601.         case Z8000_R2: RW( 2) = val; break;
  602.         case Z8000_R3: RW( 3) = val; break;
  603.         case Z8000_R4: RW( 4) = val; break;
  604.         case Z8000_R5: RW( 5) = val; break;
  605.         case Z8000_R6: RW( 6) = val; break;
  606.         case Z8000_R7: RW( 7) = val; break;
  607.         case Z8000_R8: RW( 8) = val; break;
  608.         case Z8000_R9: RW( 9) = val; break;
  609.         case Z8000_R10: RW(10) = val; break;
  610.         case Z8000_R11: RW(11) = val; break;
  611.         case Z8000_R12: RW(12) = val; break;
  612.         case Z8000_R13: RW(13) = val; break;
  613.         case Z8000_R14: RW(14) = val; break;
  614.         case Z8000_R15: RW(15) = val; break;
  615.         case Z8000_NMI_STATE: Z.nmi_state = val; break;
  616.         case Z8000_NVI_STATE: Z.irq_state[0] = val; break;
  617.         case Z8000_VI_STATE: Z.irq_state[1] = val; break;
  618.         default:
  619.             if( regnum < REG_SP_CONTENTS )
  620.             {
  621.                 unsigned offset = NSP + 2 * (REG_SP_CONTENTS - regnum);
  622.                 if( offset < 0xffff )
  623.                     WRMEM_W( offset, val & 0xffff );
  624.             }
  625.     }
  626. }
  627.  
  628. void z8000_set_nmi_line(int state)
  629. {
  630.     if (Z.nmi_state == state)
  631.         return;
  632.  
  633.     Z.nmi_state = state;
  634.  
  635.     if (state != CLEAR_LINE)
  636.     {
  637.         if (IRQ_SRV >= Z8000_NMI)    /* no NMIs inside trap */
  638.             return;
  639.         IRQ_REQ = Z8000_NMI;
  640.         IRQ_VEC = NMI;
  641.     }
  642. }
  643.  
  644. void z8000_set_irq_line(int irqline, int state)
  645. {
  646.     Z.irq_state[irqline] = state;
  647.     if (irqline == 0)
  648.     {
  649.         if (state == CLEAR_LINE)
  650.         {
  651.             if (!(FCW & F_NVIE))
  652.                 IRQ_REQ &= ~Z8000_NVI;
  653.         }
  654.         else
  655.         {
  656.             if (FCW & F_NVIE)
  657.                 IRQ_REQ |= Z8000_NVI;
  658.         }
  659.     }
  660.     else
  661.     {
  662.         if (state == CLEAR_LINE)
  663.         {
  664.             if (!(FCW & F_VIE))
  665.                 IRQ_REQ &= ~Z8000_VI;
  666.         }
  667.         else
  668.         {
  669.             if (FCW & F_VIE)
  670.                 IRQ_REQ |= Z8000_VI;
  671.         }
  672.     }
  673. }
  674.  
  675. void z8000_set_irq_callback(int (*callback)(int irqline))
  676. {
  677.     Z.irq_callback = callback;
  678. }
  679.  
  680. /****************************************************************************
  681.  * Return a formatted string for a register
  682.  ****************************************************************************/
  683. const char *z8000_info(void *context, int regnum)
  684. {
  685.     static char buffer[32][47+1];
  686.     static int which = 0;
  687.     z8000_Regs *r = (z8000_Regs *)context;
  688.  
  689.     which = ++which % 32;
  690.     buffer[which][0] = '\0';
  691.     if( !context )
  692.         r = &Z;
  693.  
  694.     switch( regnum )
  695.     {
  696.         case CPU_INFO_NAME: return "Z8002";
  697.         case CPU_INFO_FAMILY: return "Zilog Z8000";
  698.         case CPU_INFO_VERSION: return "1.1";
  699.         case CPU_INFO_FILE: return __FILE__;
  700.         case CPU_INFO_CREDITS: return "Copyright (C) 1998,1999 Juergen Buchmueller, all rights reserved.";
  701.  
  702.         case CPU_INFO_REG_LAYOUT: return (const char*)z8000_reg_layout;
  703.         case CPU_INFO_WIN_LAYOUT: return (const char*)z8000_win_layout;
  704.  
  705.         case CPU_INFO_FLAGS:
  706.             sprintf(buffer[which], "%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c",
  707.                 r->fcw & 0x8000 ? 's':'.',
  708.                 r->fcw & 0x4000 ? 'n':'.',
  709.                 r->fcw & 0x2000 ? 'e':'.',
  710.                 r->fcw & 0x1000 ? '2':'.',
  711.                 r->fcw & 0x0800 ? '1':'.',
  712.                 r->fcw & 0x0400 ? '?':'.',
  713.                 r->fcw & 0x0200 ? '?':'.',
  714.                 r->fcw & 0x0100 ? '?':'.',
  715.                 r->fcw & 0x0080 ? 'C':'.',
  716.                 r->fcw & 0x0040 ? 'Z':'.',
  717.                 r->fcw & 0x0020 ? 'S':'.',
  718.                 r->fcw & 0x0010 ? 'V':'.',
  719.                 r->fcw & 0x0008 ? 'D':'.',
  720.                 r->fcw & 0x0004 ? 'H':'.',
  721.                 r->fcw & 0x0002 ? '?':'.',
  722.                 r->fcw & 0x0001 ? '?':'.');
  723.             break;
  724.         case CPU_INFO_REG+Z8000_PC: sprintf(buffer[which], "PC :%04X", r->pc); break;
  725.         case CPU_INFO_REG+Z8000_NSP: sprintf(buffer[which], "SP :%04X", r->nsp); break;
  726.         case CPU_INFO_REG+Z8000_FCW: sprintf(buffer[which], "FCW:%04X", r->fcw); break;
  727.         case CPU_INFO_REG+Z8000_PSAP: sprintf(buffer[which], "NSP:%04X", r->psap); break;
  728.         case CPU_INFO_REG+Z8000_REFRESH: sprintf(buffer[which], "REFR:%04X", r->refresh); break;
  729.         case CPU_INFO_REG+Z8000_IRQ_REQ: sprintf(buffer[which], "IRQR:%04X", r->irq_req); break;
  730.         case CPU_INFO_REG+Z8000_IRQ_SRV: sprintf(buffer[which], "IRQS:%04X", r->irq_srv); break;
  731.         case CPU_INFO_REG+Z8000_IRQ_VEC: sprintf(buffer[which], "IRQV:%04X", r->irq_vec); break;
  732. #ifdef    LSB_FIRST
  733. #define REG_XOR 3
  734. #else
  735. #define REG_XOR 0
  736. #endif
  737.         case CPU_INFO_REG+Z8000_R0: sprintf(buffer[which], "R0 :%04X", r->regs.W[ 0^REG_XOR]); break;
  738.         case CPU_INFO_REG+Z8000_R1: sprintf(buffer[which], "R1 :%04X", r->regs.W[ 1^REG_XOR]); break;
  739.         case CPU_INFO_REG+Z8000_R2: sprintf(buffer[which], "R2 :%04X", r->regs.W[ 2^REG_XOR]); break;
  740.         case CPU_INFO_REG+Z8000_R3: sprintf(buffer[which], "R3 :%04X", r->regs.W[ 3^REG_XOR]); break;
  741.         case CPU_INFO_REG+Z8000_R4: sprintf(buffer[which], "R4 :%04X", r->regs.W[ 4^REG_XOR]); break;
  742.         case CPU_INFO_REG+Z8000_R5: sprintf(buffer[which], "R5 :%04X", r->regs.W[ 5^REG_XOR]); break;
  743.         case CPU_INFO_REG+Z8000_R6: sprintf(buffer[which], "R6 :%04X", r->regs.W[ 6^REG_XOR]); break;
  744.         case CPU_INFO_REG+Z8000_R7: sprintf(buffer[which], "R7 :%04X", r->regs.W[ 7^REG_XOR]); break;
  745.         case CPU_INFO_REG+Z8000_R8: sprintf(buffer[which], "R8 :%04X", r->regs.W[ 8^REG_XOR]); break;
  746.         case CPU_INFO_REG+Z8000_R9: sprintf(buffer[which], "R9 :%04X", r->regs.W[ 9^REG_XOR]); break;
  747.         case CPU_INFO_REG+Z8000_R10: sprintf(buffer[which], "R10:%04X", r->regs.W[10^REG_XOR]); break;
  748.         case CPU_INFO_REG+Z8000_R11: sprintf(buffer[which], "R11:%04X", r->regs.W[11^REG_XOR]); break;
  749.         case CPU_INFO_REG+Z8000_R12: sprintf(buffer[which], "R12:%04X", r->regs.W[12^REG_XOR]); break;
  750.         case CPU_INFO_REG+Z8000_R13: sprintf(buffer[which], "R13:%04X", r->regs.W[13^REG_XOR]); break;
  751.         case CPU_INFO_REG+Z8000_R14: sprintf(buffer[which], "R14:%04X", r->regs.W[14^REG_XOR]); break;
  752.         case CPU_INFO_REG+Z8000_R15: sprintf(buffer[which], "R15:%04X", r->regs.W[15^REG_XOR]); break;
  753.         case CPU_INFO_REG+Z8000_NMI_STATE: sprintf(buffer[which], "NMI:%X", r->nmi_state); break;
  754.         case CPU_INFO_REG+Z8000_NVI_STATE: sprintf(buffer[which], "NVI:%X", r->irq_state[0]); break;
  755.         case CPU_INFO_REG+Z8000_VI_STATE: sprintf(buffer[which], "VI :%X", r->irq_state[1]); break;
  756.     }
  757.     return buffer[which];
  758. }
  759.  
  760.  
  761. unsigned z8000_dasm(char *buffer, unsigned pc)
  762. {
  763. #ifdef MAME_DEBUG
  764.     return DasmZ8000(buffer,pc);
  765. #else
  766.     sprintf( buffer, "$%04X", cpu_readop16(pc) );
  767.     return 2;
  768. #endif
  769. }
  770.  
  771.